---
slug: 2023-03-02-workshop-decomposition
title: О декомпозиции проекта при работе с множествами объектов
authors: [aladin]
tags: [семинар]
---

На данном семинаре обсуждались возникшие вопросы о [лабораторной работе №2](/docs/labs/lab2) и рассматривались способы декомпозиции проекта при работе с множествами объектов.

<!--truncate-->

## Декомпозиция проекта при работе с множествами объектов

### Исходная задача

Исходная задача и первый подход к декомпозиции представлен в [примере](/docs/labs/lab2/Instructions/Example5) для [лабораторной работы №2](/docs/labs/lab2).

## Подход 2: хранение множества объектов в классе-агрегат

Объектно-ориентированный подход, как упоминается в лекции ["Концепции и парадигмы программирования"](/docs/lectures/programming-concepts-and-paradigms/), принес в мир программирования множество подходов к декомпозиции программ, проектов, систем. Давайте воспользуемся одним из подходов и к нашей задаче.

Давайте переложим ответственность за хранение нашего множества объектов на класс-агрегат.

**Агрегат** или **аггрегат** (лат. *aggregatus* — соединённый, собранный) — нечто составное, совокупность элементов, образующих систему или её часть.

Один из вариантов реализации класса-агрегата `Rectangles` выглядит следующим образом:

```cpp
#include <iostream>

class Rectangle {
private:
    int a_, b_;
public:
    Rectangle() {}

    Rectangle(int a, int b) {
        this->a_ = a;
        this->b_ = b;
    }

    // highlight-start
    Rectangle(const Rectangle &rec) {
        this->a_ = rec.a_;
        this->b_ = rec.b_;
    }
    // highlight-end

    int getA() {
        return a_;
    }

    int getB() {
        return b_;
    }

    void setA(int a) {
        this->a_ = a;
    }

    void setB(int b) {
        this->b_ = b;
    }

    void set(int a, int b) {
        setA(a);
        setB(b);
    }

    // highlight-start
    Rectangle &operator=(const Rectangle &right) {
        if (this == &right) {
            return *this;
        }
        setA(right.a_);
        setB(right.b_);
        return *this;
    }
    // highlight-end
};

// highlight-start
class Rectangles {
    Rectangle *arr_;
    int n_;
private:
    void resize(int n) {
        if (n_ == 0) {
            this->arr_ = new Rectangle[n];
            this->n_ = n;
            return;
        }
        this->n_ = n;
        this->arr_ = static_cast<Rectangle *>(realloc(this->arr_, sizeof(Rectangle) * n));
    }

public:
    Rectangles() {}

    ~Rectangles() {
        if (arr_ != nullptr) {
            delete[] this->arr_;
        }
    }

    void add(const Rectangle *rec) {
        resize(this->n_ + 1);
        this->arr_[n_ - 1] = *rec;
    }

    void showRectangles() {
        for (int i = 0; i < this->n_; i++) {
            std::cout << "I know about the rectangle # " << i
                      << ". It has: " << std::endl;
            std::cout << " a=" << this->arr_[i].getA() << std::endl;
            std::cout << " b=" << this->arr_[i].getB() << std::endl;
        }
    }

    int calculateAreas() {
        int sum = 0;
        for (int i = 0; i < this->n_; i++) {
            sum += this->arr_[i].getA() * this->arr_[i].getB();
        }
        return sum;
    }
};
// highlight-end

int main() {
    // highlight-start
    Rectangles *recs = new Rectangles();
    Rectangle *rec1 = new Rectangle(1, 3);
    Rectangle *rec2 = new Rectangle(4, 6);
    recs->add(rec1);
    recs->add(rec2);

    recs->showRectangles();
    std::cout << std::endl;
    std::cout << "Sum of the areas of all rectangles: "
              << recs->calculateAreas() << std::endl;
    delete recs;
    delete rec1;
    delete rec2;
    // highlight-end
}
```

Обратите внимание на то, что:

1. В примере показывается:
   1. Реализация расширения динамического массива.
   2. Реализация конструктора копирования и перегрузка оператора `=`.
2. Необходимо реализовать деконструктор класса, если в объекте используется выделенная вручную память.
3. Если объект создан с помощью операции `new`, то для его уничтожения применяется операция `delete`.

В результате мы получаем элегантное решение и распределение ответственности между составляющими проекта, используя принципы ООП.

## Дополнительная информация

В оставшееся свободное время предлагается обсудить следующие вопросы:

1. Использование консольных команд:
   1. [Полезные консольные команды для Linux](/docs/labs/lab1/UsefulInformation/LinuxCommands)
